home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_138 / amigaline / amigaline8 < prev    next >
Text File  |  1992-05-06  |  8KB  |  277 lines

  1.             Technical Note #8
  2.       All about keymaps and getting input from the keyboard
  3.  
  4. SUMMARY
  5.  
  6. $ 8/0 All about keymaps and getting input from the keyboard
  7. $ release
  8. $ 29-Jan-88 Bryce Nesbitt / TVD
  9. $ RAWKEY, VANILLAKEY, setmap, keymap, international, DeadKeyConvert()
  10. $ See Also: AmigaMail July/August 1987, AmigaLine #9
  11.  
  12.     There are at least 16 different keyboard configurations for the Amiga.
  13.     If your application expects to work on all of these, it must handle the
  14.     keyboard properly.  Complete, working examples are included.
  15.  
  16. ----------------------------------------------------------------------------
  17.  
  18. RAWKEY
  19.  
  20.     If your program processes Intuition RAWKEY messages, it is only half
  21.     baked!  Raw key codes give physical positions; they do not imply
  22.     *anything* about what might be marked on the top of the key.  There are
  23.     a *least* 16 different keyboard configurations available for the Amiga.
  24.  
  25.     RAWKEY messages are ok to use directly for positional control (say, up,
  26.     down, left, and right controls for a game).  They are not acceptable
  27.     for entering *any* sort of text.
  28.  
  29.     RAWKEY messages must be converted with the DeadKeyConvert() function. A
  30.     tutorial is provided.
  31.  
  32.  
  33. VANILLAKEY
  34.  
  35.     If you don't want the hassle of RAWKEYS, just change "RAWKEY" to
  36.     "VANILLAKEY" in your program.  The keys will come through already
  37.     cooked.
  38.  
  39.     The disadvantage is you only get the keys that map to a single
  40.     character.    This eliminates the function, help, and cursor keys.
  41.  
  42.  
  43. CONSOLE DEVICE, CON:, RAW:, CLI, String Gadgets
  44.  
  45.     The console device, CON:, RAW:, CLI, and String Gadgets all provide
  46.     automatic keymap conversion.  Nothing else needed.
  47.  
  48.  
  49. DEAD KEYS
  50.  
  51.     Dead keys are a feature of V.2 Kickstart.  They are used to add accents
  52.     to letters.  To try this out, click into a CLI.  Press and release "ALT
  53.     K".  Now press a letter key such as "a".  It should come out with an
  54.     umlaut.  This is an automatic feature of the keymap conversion process.
  55.  
  56.     Be sure to test to see if accented characters work in your application.
  57.  
  58.  
  59. CUSTOM KEYMAPS
  60.  
  61.     If you wish to build a custom keymap, example source code is provided
  62.     In AmigaLine #9.  This must be put in the "devs:keymaps" drawer, and
  63.     activated with "SetMap".
  64.  
  65.     If your program needs to change a keymap during execution, it must copy
  66.     the current map, modifiy it, then use the modification.
  67.  
  68.  
  69. THE NEW MACHINES
  70.  
  71.     The A500 and A2000 machines add 5 extra keys to the keyboard.  What's
  72.     on top of these keys depends on what country the machine is sold in.
  73.     For the United States the "usa1" keymap knows about the extra keys.
  74.     "usa2" provides the same features with a DVORAK layout.
  75.  
  76.     As of V1.2, Kickstart itself had not been updated to know about the
  77.     keys, or to return the "NUMERICPAD" quailifer when they are pressed.
  78.  
  79.  
  80. DISTRIBUTION DISKS
  81.  
  82.     If you distribute a bootable Workbench disk, it should contain the
  83.     "SetMap" program and the "devs:keymaps" drawer.  This allows a person
  84.     to set up the keymaps to match their keyboard.
  85.  
  86.     Better yet, allow the user to boot up with their normal Workbench, and
  87.     click on your icon to start.
  88.  
  89.     Some of the old international A1000 keyboards do not have the same
  90.     stuff on the tops of the keys as the new international A500/A2000
  91.     keyboards.    Owners of these machines will need to copy their keymap
  92.     over to your disk.
  93.  
  94.  
  95.  
  96. -------Setup needed to use DeadKeyConvert--------
  97. /* Manx users must remove the "ConsoleDevice" line from functions.h */
  98. struct Device    *ConsoleDevice;
  99. struct IOStdReq console_IO;    /* empty, zeroed IOStdReq */
  100. ....
  101.     if ( OpenDevice("console.device",-1L,(struct IORequest *)&console_IO,0L) )
  102.     cleanexit(21);
  103.     ConsoleDevice=(struct Device *)console_IO.io_Device;
  104. ....
  105.     if (ConsoleDevice)  CloseDevice  ((struct IORequest *)&console_IO);
  106. ....
  107.  
  108. ----------------DeadKeyConvert.c----------------
  109. #include "exec/types.h"
  110. #include "devices/inputevent.h"
  111. #include "intuition/intuition.h"
  112.  
  113. /*
  114.  * DeadKeyConvert().  Adapted from the Amiga Enhancer Manual
  115.  * by Bryce Nesbitt.
  116.  *
  117.  * Takes an Intuition RAWKEY message and processes it.
  118.  * The result will be "cooked" keys and key conversions in
  119.  * your buffer.
  120.  *
  121.  * The console.device must be open to use this function.
  122.  *
  123.  * The message passed to this must be of Class RAWKEY.
  124.  * Returns -1 if the buffer overflowed, or the
  125.  * number of characters converted if all was ok.
  126.  *
  127.  */
  128. long DeadKeyConvert(msg,kbuffer,kbsize,kmap)
  129. struct IntuiMessage *msg;    /* Message to be converted  */
  130. UBYTE            *kbuffer;    /* Pointer to your buffer   */
  131. long            kbsize;    /* Size of your buffer        */
  132. struct KeyMap        *kmap;    /* Custom keymap, or Zero   */
  133. {
  134. struct InputEvent ievent;
  135.  
  136.     /* if (msg->Class != RAWKEY) return(-2); */
  137.     if (msg->Code & IECODE_UP_PREFIX)
  138.     return(0);  /* Nothing to do for key up messages */
  139.  
  140.     /* pack message into an input event */
  141.     ievent.ie_NextEvent =0;
  142.     ievent.ie_SubClass    =0;
  143.     ievent.ie_Class    =IECLASS_RAWKEY;
  144.     ievent.ie_Code    =msg->Code;
  145.     ievent.ie_Qualifier =msg->Qualifier;
  146.  
  147.     /* get previous codes from location pointed to by IAddress
  148.      * this "magic" pointer is valid intil the IntuiMessage is
  149.      * replied */
  150.     ievent.ie_position.ie_addr =*((APTR*)msg->IAddress);
  151.  
  152.     return(RawKeyConvert(&ievent,kbuffer,kbsize,kmap));
  153. }
  154.  
  155.  
  156. ----------------Complete example-----------------
  157.  
  158. /*
  159.  * 29-Jan-88 Bryce Nesbitt
  160.  *
  161.  * WARNING: In order to compile this program, Manx Aztec C needs to have the
  162.  * line in functions.h that declares "ConsoleDevice();" removed.
  163.  *
  164.  */
  165. #undef LATTICE_4   /* Change to #undef for Manx */
  166. #ifdef LATTICE_4
  167. #include "proto/exec.h"
  168. #include "proto/intuition.h"
  169. #else
  170. #include "functions.h"
  171. extern int Enable_Abort;
  172. #endif
  173. #include "exec/types.h"
  174. #include "intuition/intuition.h"
  175.  
  176.  
  177. struct IntuitionBase *IntuitionBase;
  178. struct GfxBase         *GfxBase;
  179. struct Device         *ConsoleDevice;
  180.  
  181. static char buffer[16];         /* buffer to convert into */
  182. struct IOStdReq     console_IO;     /* empty, zeroed IOStdReq */
  183. struct NewWindow    MyNewWindow=
  184.     {
  185.     0,11,200,32,
  186.     1,3,
  187.     RAWKEY|CLOSEWINDOW,
  188.     WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG|
  189.     SIMPLE_REFRESH|NOCAREREFRESH|ACTIVATE,
  190.     0,0,
  191.     (UBYTE *)"Keymapper",
  192.     0,0,
  193.     64,64,
  194.     -1,-1,  /* No need to limit window growth */
  195.     WBENCHSCREEN,
  196.     };
  197. struct Window        *MyWindow;
  198. struct IntuiMessage *message;
  199.  
  200.  
  201.  
  202. #ifdef LATTICE_4
  203. CXBREAK()       /* Disable break for Lattice C */
  204. {
  205.     return(0);
  206. }
  207. #endif
  208.  
  209.  
  210.  
  211. void cleanexit(value)
  212. int value;
  213. {
  214.     if (MyWindow)       CloseWindow  (MyWindow);
  215.     if (IntuitionBase)  CloseLibrary ((struct Library *)IntuitionBase);
  216.     if (GfxBase)        CloseLibrary ((struct Library *)GfxBase);
  217.     if (ConsoleDevice)  CloseDevice  ((struct IORequest *)&console_IO);
  218.  
  219.     exit(value);
  220. }
  221.  
  222.  
  223.  
  224. void main()
  225. {
  226. long temp;
  227.  
  228. #ifndef LATTICE_4
  229.     Enable_Abort=0;
  230. #endif
  231.  
  232.     if (!( IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",33L) ))
  233.     cleanexit(20);
  234.     if (!( GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",33L) ))
  235.     cleanexit(20);
  236.     if (!( MyWindow=OpenWindow(&MyNewWindow) ))
  237.     cleanexit(20);
  238.  
  239.     /*
  240.      *
  241.      * It is not mentioned in the manuals, but the console.device may be
  242.      * opened without attaching it to a window.   To do this, open the device
  243.      * with a unit of -1 and zeroed IOStdReq block.  The console.device
  244.      * pointer will be returned in io_Device.
  245.      *
  246.      * The console.device is also a library... the returned pointer will
  247.      * be used to make calls to it.
  248.      *
  249.      */
  250.     if ( OpenDevice("console.device",-1L,(struct IORequest *)&console_IO,0L) )
  251.     cleanexit(21);
  252.     ConsoleDevice=(struct Device *)console_IO.io_Device;
  253.  
  254.     for(;;)
  255.     {
  256.     WaitPort(MyWindow->UserPort);   /* Wait for one or more messages */
  257.     while( message=(struct IntuiMessage *)GetMsg(MyWindow->UserPort) )
  258.         {
  259.         switch (message->Class)
  260.         {
  261.         case RAWKEY:
  262.             strcpy(&buffer,"               "); /* clear out buffer */
  263.             temp=DeadKeyConvert(message,&buffer,15L,0L);
  264.             Move(MyWindow->RPort,66L,22L);
  265.             Text(MyWindow->RPort,&buffer,15L);
  266.             break;
  267.  
  268.         case CLOSEWINDOW:
  269.             cleanexit(0);
  270.         }
  271.         ReplyMsg((struct Message *)message);
  272.         }
  273.     }
  274. }
  275.  
  276.  
  277.